19. Servlet

使用 Servlet

  1. 创建一个类,实现 Servlet 接口
  2. 在 web.xml 中注册这个实现类
  3. Tomcat (Servlet 容器)会创建实现对象

Servlet 执行流程

  1. 发送请求
  2. 匹配 web.xml 中的 url
  3. 根据 url-pattern 标签寻找 servlet-name
  4. 根据 servlet-name 寻找 servlet-class,找到所对应的类
  5. 之类 service 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>tomcatdemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itguigu.servlet.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/api/hello</url-pattern>
</servlet-mapping>
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.itguigu.servlet;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloServlet implements Servlet{

@Override
public void destroy() {
System.out.println("destroy");
}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
}

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service");
}
}

Servlet生命周期

  1. 构造器。在整个生命周期中只执行一次,在第一次接受到请求时执行。
  2. init。在整个生命周期中只执行一次,在第一次接受到请求时执行。
  3. service。在整个生命周期中只执行多次,每次接受到请求时都会执行。
  4. destory。在整个生命周期中只执行一次,关闭服务器时执行。

ServletConfig

定义

servlet 的配置对象。

作用

  1. getInitParamter,获取 Servlet 初始化参数(当前Servlet的)
  2. getServletContext,获取 ServletContext 对象
  3. getServletName,获取 Servlet 名字

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>tomcatdemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itguigu.servlet.HelloServlet</servlet-class>

<init-param>
<param-name>age</param-name>
<param-value>19</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/api/hello</url-pattern>
</servlet-mapping>

</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.itguigu.servlet;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloServlet implements Servlet{
private ServletConfig servletConfig;

@Override
public void destroy() {
System.out.println("destroy");
}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
// 获取 servletConfig 对象
servletConfig = config;
}

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service");

// 获取初始化参数
String initParameter = servletConfig.getInitParameter("age");
System.out.println(initParameter); // 19

// 获取 servletContext 对象
ServletContext servletContext = servletConfig.getServletContext();
System.out.println(servletContext); // org.apache.catalina.core.ApplicationContextFacade@42ad1fbf

// 获取 servlet 名称
String servletName = servletConfig.getServletName();
System.out.println(servletName); // HelloServlet
}
}

ServletContext

定义

servlet 的上下文对象

作用

  1. getInitParamter,获取 Servlet 初始化参数(全局的)
  2. getRealPath,获取项目的真实路径
  3. 域对象

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>tomcatdemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<context-param>
<param-name>agee</param-name>
<param-value>199</param-value>
</context-param>

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itguigu.servlet.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/api/hello</url-pattern>
</servlet-mapping>

</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.itguigu.servlet;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloServlet implements Servlet{
private ServletConfig servletConfig;

@Override
public void destroy() {
System.out.println("destroy");
}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
// 获取 servletConfig 对象
servletConfig = config;
}

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service");
// 获取 servletContext 对象
ServletContext servletContext = servletConfig.getServletContext();

String initParameter = servletContext.getInitParameter("agee");
System.out.println(initParameter); // 199

String realPath = servletContext.getRealPath("index.html");
System.out.println(realPath);
// /Users/rex/Documents/Projects/java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tomcatdemo/index.html
}
}

最终创建 Servlet 方式

上面的方式创建 Servlet 是实现 Servlet 接口,然后重写方法,然后自己配置 web.xml,我们只需关系 service 方法即可,其他的可以不用关心。那么我们可以直接继承 HttpServlet。其原理的是 你的类 —继承—> HttpServlet —继承—> GenericServlet —实现—> Servlet。这样能大大简化我们的使用。

在 GenericServlet 中主要实现了两个功能。

  1. 通过 getServletConfig能获取到 config 对象。通过 getServletContext 能获取到 ServletContext 对象。
  2. 抽象了 service 了方法。让 GenericServlet 的子类必须重写该方法。

在 HttpServlet 中主要做了一下功能

  1. 因为继承了GenericServlet,所以重写了 Service 方法,并将 SerletRequest,强转成了 HttpSerletRequest 类型。将 SerletResponse,强转成了 HttpSerletResponse 类型。并且调用了重载的 service 方法。
  2. 重载了 service 方法。根据 request.getMethod 来获取当前的调用方法,然后根据方法调用不同的函数处理请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>tomcatdemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>agee</param-name>
<param-value>199</param-value>
</context-param>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itguigu.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/api/hello</url-pattern>
</servlet-mapping>

<!-- 以下为新建 servlet 类型自动生成 -->
<servlet>
<description></description>
<display-name>EndServlet</display-name>
<servlet-name>EndServlet</servlet-name>
<servlet-class>com.itguigu.endservlet.EndServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EndServlet</servlet-name>
<url-pattern>/EndServlet</url-pattern>
</servlet-mapping>
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.itguigu.endservlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EndServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

public EndServlet() {
super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用了 get 方法");
response.getWriter().append("Served at: ").append(request.getContextPath());
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用了 post 方法");
doGet(request, response);
}
}